package com.gz.utils;

import com.arronlong.httpclientutil.HttpClientUtil;
import com.arronlong.httpclientutil.builder.HCB;
import com.arronlong.httpclientutil.common.HttpConfig;
import com.arronlong.httpclientutil.common.HttpHeader;
import com.arronlong.httpclientutil.common.SSLs;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.Header;
import org.apache.http.client.HttpClient;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.Random;

public class Sms {


    /**
     * 产品密钥ID，产品标识
     */
    private final static String SECRETID = "3dac00f56ab1a95deb148660a9feca4f";
    /**
     * 产品私有密钥，服务端生成签名信息使用，请严格保管，避免泄露
     */
    private final static String SECRETKEY = "0bae165843aeac2d4ec8f2bffed8e712";
    /**
     * 业务ID，易盾根据产品业务特点分配
     */
    private final static String BUSINESSID = "ee50c750ae2f4f6ea719e93e5f22b045";
    /**
     * 本机认证服务身份证实人认证在线检测接口地址
     */
    private final static String API_URL = "https://sms.dun.163yun.com/v2/sendsms";
    /**
     * 实例化HttpClient，发送http请求使用，可根据需要自行调参
     */

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    /**
     * @param
     * @throws Exception
     */
    public static String send(String mobile, String code) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        // 1.设置公共参数
        params.put("secretId", SECRETID);
        params.put("businessId", BUSINESSID);
        params.put("version", "v2");
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        //32随机字符串
        params.put("nonce", getRandomChar(32, 200));
//        params.put("nonce", "dh2u81hdah129zjk2hlla118snebd2q1");
        // 2.设置私有参数d
        params.put("mobile", mobile);
        params.put("params", "code=" + code);
        params.put("templateId", "10322");
        //需要上行的时候,这里需要设置为true
        params.put("needUp", "true");

        // 3.生成签名信息
        String signature = genSignature(SECRETKEY, params);
        params.put("signature", signature);
        // 4.发送HTTP请求，这里使用的是HttpClient工具包，产品可自行选择自己熟悉的工具包发送请求
        Header[] headers = HttpHeader.custom()
                .userAgent("javacl")
                .other("customer", "自定义")
                .build();
        HCB hcb = HCB.custom()
                .timeout(1000) //超时
                .pool(100, 10) //启用连接池，每个路由最大创建10个链接，总连接数限制为100个
                .sslpv(SSLs.SSLProtocolVersion.TLSv1_2)    //设置ssl版本号，默认SSLv3，也可以调用sslpv("TLSv1.2")
                .ssl()        //https，支持自定义ssl证书路径和密码，ssl(String keyStorePath, String keyStorepass)
                .retry(5)        //重试5次
                ;

        HttpClient client = hcb.build();


        //插件式配置请求参数（网址、请求参数、编码、client）
        HttpConfig config = HttpConfig.custom()
                .headers(headers)    //设置headers，不需要时则无需设置
                .url(API_URL)              //设置请求的url
                .map(params)              //设置请求参数，没有则无需设置
                .encoding("utf-8") //设置请求和返回编码，默认就是Charset.defaultCharset()
                .client(client)    //如果只是简单使用，无需设置，会自动获取默认的一个client对象
                //.inenc("utf-8")  //设置请求编码，如果请求返回一直，不需要再单独设置
                //.inenc("utf-8")	//设置返回编码，如果请求返回一直，不需要再单独设置
                //.json("json字符串")                          //json方式请求的话，就不用设置map方法，当然二者可以共用。
                //.context(HttpCookies.custom().getContext()) //设置cookie，用于完成携带cookie的操作
                //.out(new FileOutputStream("保存地址"))       //下载的话，设置这个方法,否则不要设置
                //.files(new String[]{"d:/1.txt","d:/2.txt"}) //上传的话，传递文件路径，一般还需map配置，设置服务器保存路径
                ;


        String result = HttpClientUtil.post(config);
        return  result;
    }

    /**
     * 生成签名信息
     *
     * @param secretKey 产品私钥
     * @param params    接口请求参数名和参数值map，不包括signature参数名
     * @return
     */
    public static String genSignature(String secretKey, Map<String, Object> params) throws UnsupportedEncodingException {
        // 1. 参数名按照ASCII码表升序排序
        String[] keys = params.keySet().toArray(new String[0]);
        Arrays.sort(keys);

        // 2. 按照排序拼接参数名与参数值
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            sb.append(key).append(params.get(key));
        }
        // 3. 将secretKey拼接到最后
        sb.append(secretKey);

        // 4. MD5是128位长度的摘要算法，转换为十六进制之后长度为32字符
        return DigestUtils.md5Hex(sb.toString().getBytes("UTF-8"));
    }

    private static String[] lowercase = {
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
            "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};

    private static String[] capital = {
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
            "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    private static String[] number = {
            "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};

    private static String[] sign = {
            "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "`", "-", "=",
            "{", "}", "|", ":", "\"", "<", ">", "?",
            "[", "]", "\\", ";", "'", ",", ".", "/"};

    //随机生成常见汉字
    public static String getChineseRandomChar() {
        String str = "";
        int highCode;
        int lowCode;

        Random random = new Random();

        highCode = (176 + Math.abs(random.nextInt(39))); //B0 + 0~39(16~55) 一级汉字所占区
        lowCode = (161 + Math.abs(random.nextInt(93))); //A1 + 0~93 每区有94个汉字

        byte[] b = new byte[2];
        b[0] = (Integer.valueOf(highCode)).byteValue();
        b[1] = (Integer.valueOf(lowCode)).byteValue();

        try {
            str = new String(b, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 获取随机字符串
     *
     * @param len     字符串长度
     * @param simpChi 出现汉字的概率
     * @return 生成的随机字符串
     */
    public static String getRandomChar(int len, int simpChi) {
        Random random = new Random();
        StringBuffer buffer = new StringBuffer();
        int max = simpChi + lowercase.length + capital.length + number.length + sign.length;
        for (int i = 0; i < len; i++) {
            int temp = random.nextInt(max);
            if (temp < simpChi) {
                buffer.append(getChineseRandomChar());
                continue;
            }
            if (temp >= simpChi && temp < simpChi + lowercase.length) {
                buffer.append(getRandom(TYPE.LETTER));
                continue;
            }
            if (temp >= simpChi + lowercase.length && i < simpChi + lowercase.length + capital.length) {
                buffer.append(getRandom(TYPE.CAPITAL));
                continue;
            }
            if (temp >= simpChi + lowercase.length + capital.length && temp < simpChi + lowercase.length + capital.length + number.length) {
                buffer.append(getRandom(TYPE.NUMBER));
                continue;
            }
            if (temp >= simpChi + lowercase.length + capital.length + number.length && temp < max) {
                buffer.append(getRandom(TYPE.SIGN));
                continue;
            }
        }
        return buffer.toString();
    }


    public Sms() {
        super();
    }

    /**
     * 获取随机组合码
     *
     * @param type 类型
     * @type <br>小写字符型 LETTER,
     * <br>大写字符型 CAPITAL,
     * <br>数字型 NUMBER,
     * <br>符号型 SIGN
     */
    public static String getRandom(TYPE type) {
        Random random = new Random();
        ArrayList<String> temp = new ArrayList<String>();
        StringBuffer code = new StringBuffer();
        if (type == TYPE.LETTER) {
            temp.addAll(Arrays.asList(lowercase));
        } else if (type == TYPE.CAPITAL) {
            temp.addAll(Arrays.asList(capital));
        } else if (type == TYPE.NUMBER) {
            temp.addAll(Arrays.asList(number));
        } else if (type == TYPE.SIGN) {
            temp.addAll(Arrays.asList(sign));
        }
        code.append(temp.get(random.nextInt(temp.size())));

        return code.toString();
    }

    /**
     * 字符类型枚举
     */
    public static enum TYPE {
        /**
         * 字符型
         */
        LETTER,
        /**
         * 大写字符型
         */
        CAPITAL,
        /**
         * 数字型
         */
        NUMBER,
        /**
         * 符号型
         */
        SIGN
    }

    public static void main(String[] args) {
        try {
            System.out.println(send("18686703845","123"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
